﻿using UnityEngine;
using Unity.Collections;
using Unity.Entities;
using Unity.Jobs;
using Unity.Physics;
using Unity.Physics.Systems;
using Jinndev.ECS;

namespace Jinndev.Physics {

    /// <summary>
    /// 根据摄像机视野，添加或移除PhysicsCollider<br/>
    /// 需要组件：Culling, PhysicsCulling, PhysicsCollider
    /// </summary>
    [UpdateAfter(typeof(CullingSystem.ECB))]
    public class PhysicsCullingSystem : JobComponentSystem {

        [UpdateAfter(typeof(PhysicsCullingSystem))]
        [UpdateBefore(typeof(BuildPhysicsWorld))]
        public class ECB : EntityCommandBufferSystem { }

        private ECB commandBufferSystem;

        protected override void OnCreate() {
            commandBufferSystem = World.GetOrCreateSystem<ECB>();
        }

        protected override JobHandle OnUpdate(JobHandle inputDeps) {
            EntityCommandBuffer.ParallelWriter ecb = commandBufferSystem.CreateCommandBuffer().AsParallelWriter();

            // 检查新添加的Entity，为其添加PhysicsCullingEnabled组件
            inputDeps = Entities.WithAll<PhysicsCulling, PhysicsCollider, Culling>().WithNone<PhysicsCullingEnabled>().ForEach((Entity entity, int entityInQueryIndex) => {
                ecb.AddComponent<PhysicsCullingEnabled>(entityInQueryIndex, entity);
            }).Schedule(inputDeps);
            commandBufferSystem.AddJobHandleForProducer(inputDeps);
            inputDeps.Complete();

            // 从可见变不可见
            inputDeps = Entities.WithAll<Culling, Culled>().ForEach((Entity entity, int entityInQueryIndex, ref PhysicsCullingEnabled physicsCullingEnabled, in PhysicsCollider physicsCollider) => {
                physicsCullingEnabled.collider = physicsCollider;
                ecb.RemoveComponent<PhysicsCollider>(entityInQueryIndex, entity);
            }).Schedule(inputDeps);
            commandBufferSystem.AddJobHandleForProducer(inputDeps);
            inputDeps.Complete();

            // 从不可见变可见
            inputDeps = Entities.WithAll<Culling>().WithNone<Culled, PhysicsCollider>().ForEach((Entity entity, int entityInQueryIndex, in PhysicsCullingEnabled physicsCullingEnabled) => {
                ecb.AddComponent(entityInQueryIndex, entity, physicsCullingEnabled.collider);
            }).Schedule(inputDeps);
            commandBufferSystem.AddJobHandleForProducer(inputDeps);
            inputDeps.Complete();

            return inputDeps;
        }

    }

}